package com.ruoyi.system.service.impl;

import com.ruoyi.common.json.JSON;
import com.ruoyi.common.utils.TimeUtils;
import com.ruoyi.system.domain.Metrics;
import com.ruoyi.system.domain.bo.MetricsCountBo;
import com.ruoyi.system.domain.bo.MetricsTypeBo;
import com.ruoyi.system.mapper.MetricsMapper;
import com.ruoyi.system.service.MetricsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Time;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Auther: miaoguoxin
 * @Date: 2019/6/30 13:01
 * @Description:
 */
@Service
public class MetricsServiceImpl implements MetricsService {
    @Autowired
    private MetricsMapper metricsMapper;
    private static final String pattern = "yyyy-MM-dd HH:mm";
    @Override
    public Map<String, Object> list(Integer type) {

        MetricsTypeBo metricsTypeBo = convert2Type(type, pattern);
        final int interval = metricsTypeBo.getInterval();
        final String startTime = metricsTypeBo.getStartTime();
        final String endTime = metricsTypeBo.getEndTime();
        List<String> timeIntervalList = TimeUtils.getIntervalTimeList(startTime, endTime, interval, pattern);

        Map<String, Object> result = new HashMap<>();
        List<Metrics> metricsList = metricsMapper.queryBetweenTime(startTime, endTime);
        Map<String, List<Metrics>> collect = metricsList.stream().collect(Collectors.groupingBy(Metrics::getGroupByTime));
        List<MetricsCountBo> metricsResult = new ArrayList<>();
        //计算统计数据
        this.calculateAndAdd2MetricsResult(interval,timeIntervalList, collect, metricsResult);
        List<Integer> total = metricsResult.stream().map(MetricsCountBo::getTotal).collect(Collectors.toList());
        List<Integer> success = metricsResult.stream().map(MetricsCountBo::getSuccess).collect(Collectors.toList());
        List<Integer> err = metricsResult.stream().map(MetricsCountBo::getErr).collect(Collectors.toList());

        result.put("total", total);
        result.put("success", success);
        result.put("err", err);
        Date date = TimeUtils.convertString2Date(pattern, startTime);
        result.put("pointStart", TimeUtils.convertGMT2Local(date).getTime());
        result.put("pointInterval", 60 * interval * 1000);
        return result;
    }

    private void calculateAndAdd2MetricsResult(int interval, List<String> timeIntervalList, Map<String, List<Metrics>> collect, List<MetricsCountBo> metricsResult) {
        for (String time : timeIntervalList) {
            int timeIndex=1;
            int index = interval;
            MetricsCountBo countBo = new MetricsCountBo();
            this.count(collect, time, countBo);
            while (index > 1) {
                index--;
                String addTime = TimeUtils.addDateMinut(time, timeIndex++, pattern, Calendar.MINUTE);
                this.count(collect, addTime, countBo);
            }
            metricsResult.add(countBo);
        }
    }

    private void count(Map<String, List<Metrics>> collect, String time, MetricsCountBo countBo) {
        List<Metrics> list = collect.getOrDefault(time, new ArrayList<>());
        countBo.setTotal(countBo.getTotal() + list.stream().mapToInt(Metrics::getTotalCount).sum());
        countBo.setSuccess(countBo.getSuccess() + list.stream().mapToInt(Metrics::getSuccessCount).sum());
        countBo.setErr(countBo.getErr() + list.stream().mapToInt(Metrics::getErrCount).sum());
    }

    private static MetricsTypeBo convert2Type(Integer type, String datePattern) {
        MetricsTypeBo metricsTypeBo = new MetricsTypeBo();
        Date currentDate = new Date();
        metricsTypeBo.setEndTime(TimeUtils.formateDate2Str(currentDate, datePattern));
        if (type==Metrics.IN_ONE_HOUR){
            metricsTypeBo.setInterval(1);
            metricsTypeBo.setStartTime(TimeUtils.addDateMinut(metricsTypeBo.getEndTime(), -1, datePattern, Calendar.HOUR));
        } else if (type == Metrics.IN_ONE_DAY) {
            metricsTypeBo.setInterval(2);
            metricsTypeBo.setStartTime(TimeUtils.addDateMinut(metricsTypeBo.getEndTime(), -24, datePattern, Calendar.HOUR));
        }else if (type==Metrics.IN_THREE_DAY){
            metricsTypeBo.setInterval(5);
            metricsTypeBo.setStartTime(TimeUtils.addDateMinut(metricsTypeBo.getEndTime(), -24*3, datePattern, Calendar.HOUR));
        }else if(type==Metrics.IN_ONE_WEEK){
            metricsTypeBo.setInterval(8);
            metricsTypeBo.setStartTime(TimeUtils.addDateMinut(metricsTypeBo.getEndTime(), -24*7, datePattern, Calendar.HOUR));
        }
        return metricsTypeBo;
    }

    public static void main(String[] args) throws Exception {
        MetricsTypeBo metricsTypeBo = convert2Type(1, "yyyy-MM-dd HH:mm:ss");
        System.out.println(JSON.marshal(metricsTypeBo));
    }
}
